package com.lry.pda.bottom.c.frontend;


import java.util.*;

public class StateManager {

    public static int stateNum;

    //所有节点
    private List<State> stateList = new ArrayList<>();

    private List<State> compressedStateList = new ArrayList<>();

    //所有节点的所有转移关系，相当于一张状态机节点图
    //state通过 symbol跳到另一个state
    private Map<State, Map<Integer, State>> transitionMap = new HashMap<>();


    private static StateManager self;

    private boolean compressed = true;

    private StateManager(){

    }

    public static StateManager getSelf(){
        if(null==self){
            self = new StateManager();
        }
        return self;
    }

    public Map<Integer, Map<Integer, Integer>> getLRTable() {
        Iterator<State> it;
        if(compressed){
            it = compressedStateList.iterator();
        }else {
            it = stateList.iterator();
        }

        Map<Integer, Map<Integer,Integer>> lrTable = new HashMap();

        while(it.hasNext()){
            State state = it.next();
            Map<Integer, State> transMap = transitionMap.get(state);
            Map<Integer,Integer> jump = new HashMap<>();

            //shift
            if(null!=transMap){
                transMap.forEach((k,v)->{
                    jump.put(k,v.getStateNum());
                });
            }

            //reduce
            //symbol,productNum
            Map<Integer, Integer> reduceMap = state.makeReduce();
            reduceMap.forEach((k,v)->{
                jump.put(k,-v);
            });

            lrTable.put(state.getStateNum(),jump);
        }
        return lrTable;
    }

    public void buildTransitionStateMachine(){
        //构建节点0
        List<Production> productions = ProductionManager.getSelf().getProduction(CTokenType.PROGRAM.ordinal());
        State state = buildStateByProduction(productions);

        state.buildTransition();

        printTransition();
    }

    private void printTransition() {
        transitionMap.forEach((k,v)->{

            System.out.println("\r\n----------节点stateNum="+k.getStateNum()+"跳转关系如下：---------------");
            k.print();
            v.forEach((k1,v1)->{
                String symbolStr = CTokenType.getSymbolStr(k1);
                System.out.println(k.getStateNum()+"---"+symbolStr+"--->"+v1.getStateNum());
            });
            System.out.println("----------节点stateNum="+k.getStateNum()+"跳转关系如上：---------------\r\n");

        });

        List<State> states = null;
        if(compressed){
            states = compressedStateList;
        }else {
            states = stateList;
        }
        for (State state : states) {
            if(!transitionMap.containsKey(state)){
                System.out.println("\r\n----------节点stateNum="+state.getStateNum()+"跳转关系如下：---------------");
                state.print();
                System.out.println("----------节点stateNum="+state.getStateNum()+"跳转关系如上：---------------\r\n");
            }
        }
    }

    public State buildStateByProduction(List<Production> productions){
        State state = new State(productions);

        //返回旧节点
        for (State oldState : stateList) {
            if(oldState.equals(state)){
                return oldState;
            }
        }

        //新建节点
        stateList.add(state);
        stateNum++;
        return state;
    }


    public State getState(int stateNum){
        List<State> states = null;
        if(compressed){
            states = compressedStateList;
        }else {
            states = stateList;
        }
        for (State state : states) {
            if(state.getStateNum() == stateNum){
                return state;
            }
        }
        return null;
    }

    public void addTransition(State from, Integer symbol, State to) {
        if(compressed){
            from = getAndMergeSimilarStates(from);
            to = getAndMergeSimilarStates(to);
        }

        State finalTo = to;
        transitionMap.compute(from,(k, v)->{
            if(null==v){
                v = new HashMap<>();
            }
            v.put(symbol, finalTo);
            return v;
        });
    }

    //从stateList中找到和state相似的节点，表达式一样即可
    private State getAndMergeSimilarStates(State state) {
        State returnState = state;

        for (State oldState : stateList) {
            if(state.equals(oldState)){
                continue;
            }
            //如果表达式一样
            if(oldState.checkProductionEqual(state,true)){
                if(oldState.getStateNum()<state.getStateNum()){
                    oldState.stateMerge(state);
                    returnState = oldState;
                }else{
                    state.stateMerge(oldState);
                    returnState = state;
                }
                break;
            }
        }

        if(!compressedStateList.contains(returnState)){
            compressedStateList.add(returnState);
        }
        return returnState;
    }
}
